/*
 * @Author: rock
 * @Date: 2025-04-19 08:50:09
 * @LastEditors: rock
 * @LastEditTime: 2025-04-19 09:14:02
 * @FilePath: /006logger/src/logqueue.cpp
 * @Description:
 *
 * Copyright (c) 2025 by rock, All Rights Reserved.
 */
#include "logqueue.h"

/**
 * @Author: rock
 * @description: 向队列中添加日志消息
 * @param :[ const string &msg ]-> 日志消息
 * @return :[ ]
 */
void LogQueue::push(const std::string &msg)
{
    // 把字符串放到队列中
    std::lock_guard<std::mutex> lock(mtx);
    queue_.push(msg);  // 向队列中添加消息
    cond.notify_one(); // 向队列中添加了一个元素就可以通知消费者来消费
}

/**
 * @Author: rock
 * @description: 任务队列pop日志消息
 * @param :[ string &msg ]-> 传出参数, pop出的日志消息存储在msg中
 * @return :[ bool ], pop成功为true, 失败为false
 */
bool LogQueue::pop(std::string &msg)
{
    // 从队列中删除字符串, bool表示删除成功或者失败, pop存在阻塞的情况
    // 在另外一个线程加锁
    // 消费者需要判读队列是否为空
    // 判断的条件就是条件变量需要的条件
    std::unique_lock<std::mutex> lock(mtx);
    // 方式1解决虚假唤醒
    //  while (queue_.empty())
    //  {
    //      //while解决虚假唤醒
    //      cond.wait(lock);

    // }
    // 方式2解决虚假唤醒, lambda表达式返回true时继续向下执行, 向下执行时, 拥有锁
    cond.wait(lock, [this]() -> bool
              { return !queue_.empty() || is_shutdown; });
    // 条件变量在等待notify的时候是不持有锁的

    if (is_shutdown && queue_.empty())
    {
        return false;
    }

    msg = queue_.front();
    queue_.pop();

    return true;
}
/**
 * @Author: rock
 * @description: 关闭消息队列, 用来通知消费者线程等待
 * @return :[ ]
 */
void LogQueue::shutdown()
{ // 关闭
    std::lock_guard<std::mutex> lock(mtx);
    is_shutdown = true;
    cond.notify_all(); // 通知消费者线程
}